# -*- coding: utf-8 -*-
#===============================================================================
# Koro Business Environment
# Copyright (C) 2008  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================

# 04/09/2010
# modulo classi del core business
import sys
from decimal import Decimal
from sqlalchemy.orm import object_session
#from sqlalchemy import func,orm
from datetime import date
from koro import util


#===============================================================================
# Module
#===============================================================================
#class Module(object):
#    def __init__(self,name):
#        self.name=name
#        self.enabled=False
#        self.module=None
#        self.dependency=None
#        self.description=''
#        self._configure()
#    
#    def _configure(self):
#        name='koro.modules.{0}'.format(self.name)
#        mod=__import__(name,fromlist=['description','dependency'])
#        self.dependency=mod.dependency()
#        self.description=mod.description()
#    
#    def load(self):        
#        name='koro.modules.{0}'.format(self.name)
#        __import__(name)
#        self.module=sys.modules[name]
#        self.enabled=True
#    
#    def get_dependency(self):
#        if self.dependency is None:
#            return ''
#        d=''
#        for item in self.dependency:
#            d+='{0}, '.format(item.capitalize())
#        return d
#
#
#===============================================================================
# Modules
#===============================================================================
#class Modules(dict):
#    def __init__(self):
#        self.__enabled_modules=[]
#        
#    def add(self,module):
#        self[module.name]=module
#    
#    def load(self,name):
#        mod=self[name]
#        mod.load()
#        self.__enabled_modules.append(mod)
#    
#    def all(self):
#        return self.values()
#    
#    def enabled(self):
#        return tuple(self.__enabled_modules)
#        

##===============================================================================
## Indirizzo
##===============================================================================
#class Indirizzo(object):
#    def __init__(self):
#        self.via= ""
#        self.cap=""
#        self.localita=""
#        self.provincia=""
#
#    def get_via(self):
#        return self.via
#
#    def get_cap(self):
#        return self.cap
#
#    def get_localita(self):
#        return self.localita
#
#    def get_provincia(self):
#        return self.provincia
#
#    def set_via(self, value):
#        self.via = value
#
#    def set_cap(self, value):
#        self.cap = value
#
#    def set_localita(self, value):
#        self.localita = value
#
#    def set_provincia(self, value):
#        self.provincia = value
#    
#    def is_empty(self):
#        return self.via=="" and self.cap=="" and self.localita=="" and self.provincia==""
    
#
##===============================================================================
## Pagamento
##===============================================================================
#class Pagamento(object):
#    def __init__(self):
#        self.codice=None
#        self.descrizione=""
#
#    def get_codice(self):
#        return self.codice
#
#    def get_descrizione(self):
#        return self.descrizione
#
#    def set_codice(self, value):
#        self.codice = value
#
#    def set_descrizione(self, value):
#        self.descrizione = value

    
##===============================================================================
## Iva
##===============================================================================
#class Iva(object):
#    def __init__(self):
#        self.codice=None
#        self.aliquota=Decimal(0)
#        self.descrizione=""
#
#    def get_codice(self):
#        return self.codice
#
#    def get_percentuale(self):
#        return self.aliquota
#
#    def get_descrizione(self):
#        return self.descrizione
#
#    def set_codice(self, value):
#        self.codice = value
#
#    def set_percentuale(self, value):
#        self.aliquota = Decimal(value)
#
#    def set_descrizione(self, value):
#        self.descrizione = value

   
##===============================================================================
## Commerciale
##===============================================================================
#class Commerciale(object):#non serve piu' perche' ha solo le chiavi esterne
#    def __init__(self):
#        self.pagamento=None
#        self.listino=None
#        self.iva=None
#        self.sconti=''
#
#    def get_pagamento(self):
#        return self.pagamento
#
#    def get_listino(self):
#        return (self.listino or Listino())
#
#    def get_iva(self):
#        return (self.iva or Iva())
#
#    def set_pagamento(self, value):
#        self.pagamento = value
#
#    def set_listino(self, value):
#        assert isinstance(value,Listino),Exception("Atteso tipo Listino")
#        self.listino = value
#
#    def set_iva(self, value):
#        assert isinstance(value,Iva),Exception("Atteso tipo Iva")
#        self.iva = value
#    
#    def set_sconti(self,value):
#        #TODO:controllarese il formato e' giusto
#        self.sconti=value
#
#    def del_pagamento(self):
#        del self.pagamento
#
#    def del_listino(self):
#        del self.listino
#
#    def del_iva(self):
#        del self.iva


##===============================================================================
## Anagrafica
##===============================================================================
#class Anagrafica(object):
#    def __init__(self):
#        self.ID=None
#        self.ragione_sociale=''
#        self.indirizzo=None
#        self.piva=''
#        self.codfisc=''
#        self.telefono=''
#        self.fax=''
#        self.cellulare=''
#        self.email=''
#        self.sitoweb=''
#        self.note=''
#    
#    def get_piva(self):
#        return self.piva
#
#    def get_codice_fiscale(self):
#        return self.codfisc
#
#    def get_telefono(self):
#        return self.telefono
#
#    def get_fax(self):
#        return self.fax
#
#    def get_cellulare(self):
#        return self.cellulare
#
#    def get_email(self):
#        return self.email
#
#    def get_sitoweb(self):
#        return self.sitoweb
#    
#    def get_ID(self):
#        return self.ID
#
#    def get_ragione_sociale(self):
#        return self.ragione_sociale
#
#    def get_indirizzo(self):
#        if self.indirizzo is None:
#            return Indirizzo()
#        return self.indirizzo
#
#    def get_via(self):
#        if self.indirizzo is None:
#            return ''
#        return self.indirizzo.via
#    
#    def get_cap(self):
#        if self.indirizzo is None:
#            return ''
#        return self.indirizzo.cap
#    
#    def get_citta(self):
#        if self.indirizzo is None:
#            return ''
#        return self.indirizzo.localita
#    
#    def get_provincia(self):
#        if self.indirizzo is None:
#            return ''
#        return self.indirizzo.provincia
#
#    def set_ID(self, value):        
#        self.ID = util.none_if_not(value)
#
#    def set_ragione_sociale(self, value):
#        self.ragione_sociale = value
#
#    def set_indirizzo(self, value):
#        assert isinstance(value,Indirizzo)
#        if value.is_empty():
#            value=None
#            self.fk_indirizzo=None
#        self.indirizzo = value
#    
#    def set_via(self,value):
#        if self.indirizzo is None:
#            self.indirizzo=Indirizzo()
#        self.indirizzo.via=value
#    
#    def set_cap(self,value):
#        if self.indirizzo is None:
#            self.indirizzo=Indirizzo()
#        self.indirizzo.cap=value
#    
#    def set_citta(self,value):
#        if self.indirizzo is None:
#            self.indirizzo=Indirizzo()
#        self.indirizzo.localita=value
#    
#    def set_provincia(self,value):
#        if self.indirizzo is None:
#            self.indirizzo=Indirizzo()
#        self.indirizzo.provincia=value
#            
#    def set_piva(self, value):
#        self.piva = value
#
#    def set_codfisc(self, value):
#        self.codfisc = value
#
#    def set_telefono(self, value):
#        self.telefono = value
#
#    def set_fax(self, value):
#        self.fax = value
#
#    def set_cellulare(self, value):
#        self.cellulare = value
#
#    def set_email(self, value):
#        self.email = value
#
#    def set_sitoweb(self, value):
#        self.sitoweb = value
#
#    via=property(get_via,None,None,None)
#    cap=property(get_cap,None,None,None)
#    citta=property(get_citta,None,None,None)
#    provincia=property(get_provincia,None,None,None)
#
#
##===============================================================================
## ClienteFornitore
##===============================================================================
#class ClienteFornitore(Anagrafica,Commerciale):
#    def __init__(self):
#        Anagrafica.__init__(self)
#        Commerciale.__init__(self)        
#        self.desueto=False
#    
#    def is_desueto(self):
#        if not isinstance(self.desueto,bool):
#            return False        
#        return self.desueto
#
#    def set_desueto(self, value):
#        #assert isinstance(value,bool),"Cliente_setDesueto: atteso valore bool"
#        if value is None:
#            value=False
#        self.desueto = bool(value)

##===============================================================================
## Cliente
##===============================================================================
#class Cliente(Anagrafica,Commerciale):
#    def __init__(self):
#        Anagrafica.__init__(self)
#        Commerciale.__init__(self)        
#        self.desueto=False
#    
#    def is_desueto(self):
#        if not isinstance(self.desueto,bool):
#            return False        
#        return self.desueto
#
#    def set_desueto(self, value):
#        #assert isinstance(value,bool),"Cliente_setDesueto: atteso valore bool"
#        if value is None:
#            value=False
#        self.desueto = bool(value)
    

##===============================================================================
## Fornitore
##===============================================================================
#class Fornitore(Anagrafica,Commerciale):
#    def __init__(self):
#        Anagrafica.__init__(self)
#        Commerciale.__init__(self)


##===============================================================================
## CategoriaProdotto
##===============================================================================
#class CategoriaProdotto(object):
#    def __init__(self):
#        self.ID=None
#        self.nome=None
#        #self.gruppo=None
#        self.ricarico=None
#        self.servizio=False
#
#    def get_ID(self):
#        return self.ID
#
#    def get_nome(self):
#        return self.nome
#
##    def get_gruppo(self):
##        return self.gruppo
#
#    def get_ricarico(self):
#        return (self.ricarico or 0)
#    
#    def get_servizio(self):
#        return self.servizio
#
#    def set_ID(self, value):
#        self.ID = value
#
#    def set_nome(self, value):
#        self.nome = value
#
##    def set_gruppo(self, value):
##        assert isinstance(value,CategoriaProdotto) or value is None,"CategoriaProdotto: Tipo gruppo non valido."
##        self.gruppo = value
#
#    def set_ricarico(self, value):
#        self.ricarico = value
#    
#    def set_servizio(self,value):
#        self.servizio=value
#    
#
##===============================================================================
## Prodotto
##===============================================================================
#class Prodotto(object):
#    def __init__(self):
#        self.ID=None
#        self.codice=None
#        self.descrizione=None
#        #self.fornitore=None
#        #self.categoria=None
#        self.prezzi=[]
#        self.giacenza=0
#
#    def get_ID(self):
#        return self.ID
#
#    def get_codice(self):
#        return self.codice
#
#    def get_descrizione(self):
#        return self.descrizione
#
#    def get_fornitore(self):
#        if self.fornitore is None:
#            return ''
#        return self.fornitore.ragione_sociale
#
#    def get_categoria(self):
#        if self.categoria is None:
#            return CategoriaProdotto()
#        return self.categoria
#    
#    def get_prezzo_as_number(self,listino):
#        return self.get_prezzo(listino).prezzo
#    
#    def _get_prezzo(self,codice_listino):
#        if codice_listino=='':
#            return None
#        for item in self.prezzi:
#            if item.fk_listino==codice_listino:
#                return item
#        pp=PrezzoProdotto()
#        pp.set_listino(codice_listino,object_session(self))
#        pp.fk_prodotto=self.ID
#        return pp
#    
#    def get_prezzo(self,listino):
#        if listino.has_flag_ricarico():
#            prezzo_prodotto=object_session(self).query(PrezzoProdotto).\
#            filter_by(fk_prodotto=self.ID,fk_listino=listino.codice_listino_ricarico).first()
#            pp=PrezzoProdotto()
#            pp.fk_prodotto=self.ID
#            pp.fk_listino=listino.codice
#            pp.listino=listino
#            if not prezzo_prodotto is None and not prezzo_prodotto.prezzo.is_zero():
#                prezzo=(prezzo_prodotto.prezzo*listino.ricarico/100)+prezzo_prodotto.prezzo            
#                pp.prezzo=util.round(prezzo)
#            return pp
#        else:
#            return self._get_prezzo(listino.codice)
#                
#    def get_prezzi(self):        
#        listini=object_session(self).query(Listino).all()
#        prezzi=[]
#        for listino in listini:
#            prezzi.append(self.get_prezzo(listino))
#        return prezzi
#    
#    def is_servizio(self):
#        return self.categoria.servizio
#
#    def set_ID(self, value):
#        self.ID = util.none_if_not(value)
#
#    def set_codice(self, value):
#        self.codice = value
#
#    def set_descrizione(self, value):
#        self.descrizione = value
#
#    def set_fornitore(self, value):
#        assert isinstance(value,Anagrafica)        
#        self.fornitore = value
#
#    def set_categoria(self, value):
#        assert isinstance(value,CategoriaProdotto)
#        self.categoria = value
#    
#    def set_prezzo(self,codice_listino,prezzo):
#        for item in self.prezzi:
#            if item.fk_listino==codice_listino:
#                item.set_prezzo(prezzo)
#                return
#        self._add_prezzo(codice_listino,prezzo)
#    
#    def _update_prezzi(self,prezzi):
#        for item in prezzi:
#            self.set_prezzo(item[0], item[1])
#    
#    def set_prezzi(self,prezzi):
#        '''Questo metodo probabilmente verra' rimosso.
#        Il parametro prezzi e' una lista di liste. 
#        Il primo elemento e' il codice listino e il secondo il prezzo.'''
#        if len(self.prezzi)>0:
#            self._update_prezzi(prezzi)
#        else:
#            self._set_prezzi(prezzi)       
#    
#    def _set_prezzi(self,prezzi):
#        for item in prezzi:
#            self._add_prezzo(item[0],item[1])
#    
#    def _add_prezzo(self,cod_listino,prezzo):
#            prezzo_prodotto=PrezzoProdotto()
#            prezzo_prodotto.set_prezzo(prezzo)
#            
#            #if prezzo_.is_zero(): salvo anche prezzo==zero
#            #    return False
#            prezzo_prodotto.set_prodotto(self.ID)
#            prezzo_prodotto.set_listino(cod_listino,object_session(self))            
#            self.prezzi.append(prezzo_prodotto)
#            return True
#
#    def del_fornitore(self):
#        del self.fornitore
#
#    def del_categoria(self):
#        del self.categoria
#        
#    
##===============================================================================
## PrezzoProdotto
##===============================================================================
#class PrezzoProdotto(object):
#    def __init__(self):
#        #self.prodotto=None
#        self.listino=None
#        self.prezzo=Decimal('0.00')
#    
#    def set_prezzo(self,prezzo):
#        self.prezzo=Decimal(str(prezzo))    
#    
#    def set_prodotto(self,id_prodotto):
#        if id_prodotto:
#            self.fk_prodotto=int(id_prodotto)
#    
#    def set_listino(self,codice_listino,session):
#        self.fk_listino=codice_listino
#        if session is not None:
#            self.listino=session.query(Listino).filter_by(codice=codice_listino).one()
#        
#    def is_zero(self):
#        return self.prezzo.is_zero()


##===============================================================================
## Listino
##===============================================================================
#class Listino(object):
#        
#    @staticmethod
#    def configure():
#        for item in TIPI_LISTINO:
#            setattr(Listino,item.upper(),item)
#    
#    @staticmethod
#    def get_tipi_listino():
#        return tuple(TIPI_LISTINO)
#    
#    def __init__(self):
#        self.codice=None
#        self.descrizione=""
#        self.tipo=Listino.GENERICO
#        self.ricarico_flag=False
#        self.ricarico=0
#        self.codice_listino_ricarico=None
#
#    def get_tipo(self):
#        return self.tipo
#
#    def get_codice(self):
#        return self.codice
#
#    def get_descrizione(self):
#        return self.descrizione
#
#    def has_flag_ricarico(self):
#        if not isinstance(self.ricarico_flag,bool):
#            return False
#        return self.ricarico_flag
#    
#    def get_flag_ricarico_as_string(self):
#        return (self.ricarico_flag and "Si") or "No"
#
#    def get_ricarico(self):
#        return self.ricarico
#
#    def get_listino_ricarico(self):        
#        return self.codice_listino_ricarico
#    
#    def set_tipo(self, value):
#        self.tipo = value
#
#    def set_codice(self, value):
#        self.codice = value
#
#    def set_descrizione(self, value):
#        self.descrizione = value
#
#    def set_flag_ricarico(self, value):
#        self.ricarico_flag = value
#
#    def set_ricarico(self, value):
#        if value is None or value=="":
#            value ='0'        
#        self.ricarico = Decimal(value)
#
#    def set_listino_ricarico(self, value):
#        self.ricarico_listino = value    
#
#    tipi_listino = property(get_tipi_listino, None, None, "Tipo's Docstring")


#===============================================================================
# TipiStatoOrdine
#===============================================================================
class TipiStatoOrdine(object):
    def __init__(self):
        self.ID=None
        self.descrizione=''
    
    def __eq__(self,x):
        return self.ID==x
    
#    def __repr__(self):
#        print 'repr di tipi_stato_ordine'
#        return self.descrizione

#class DocumentoBase(object):
#    '''Questa classe deve essere estesa dalle classi documento.
#    Contiene i metodi comuni a tutti i documenti'''
#    
#    def get_ID(self):
#        if self.ID is None:
#            return ''
#        return self.ID
#    
#    def get_intestatario(self):
#        '''Restituisce la ragione sociale dell'intestatario documento.'''
#        if self.intestatario is None:
#            return ''
#        return self.intestatario.ragione_sociale
#    
#    def get_data_documento(self):
#        if self.data is None:
#            self.data=date.today()
#        return self.data
#    
#    def get_format_data(self):
#        if isinstance(self.data,date):
#            return util.format_date(self.data)
#        return self.data
#    
#    def get_data_documento_fmt(self):
#        return util.format_date(self.data)
#    
#    def get_iva_spese(self):
#        if self.iva_spese is None:
#            return 0
#        return self.iva_spese.aliquota
#    
#    def get_totale_spese(self):
#        return util.round(self.spese_importo+(self.spese_importo/100*self.get_iva_spese()))
#    
#    def get_totale_spese_fmt(self):
#        return util.euro(self.get_totale_spese())
#    
#    def get_iva_intestatario(self):#TODO:controllare
#        if self.intestatario is None or self.intestatario.iva is None:
#            return ''
#        return self.intestatario.iva.codice
#    
#    def get_sconti(self):
#        return ''
#    
#    def get_totale(self):
#        return self.totale_imponibile+self.totale_iva
#    
#    def get_totale_fmt(self):
#        return util.euro(self.get_totale())
#    
#    def get_totale_imponibile(self):
#        return self.totale_imponibile
#    
#    def get_totale_imponibile_fmt(self):
#        return util.euro(self.totale_imponibile)
#    
#    def get_totale_iva(self):
#        return self.totale_iva
#    
#    def get_totale_iva_fmt(self):
#        return util.euro(self.totale_iva)
#    
#    def set_ID(self, value):
#        self.ID = util.none_if_not(value)
#    
#    def set_data_documento(self, value):
#        self.data = value
#    
#    def set_totale(self, value):
#        self.totale = value
#    
#    def set_totale_imponibile(self, value):
#        self.totale_imponibile = value
#    
#    def set_totale_iva(self, value):
#        self.totale_iva = value
#        
#    def set_importo_spese(self,importo):
#        if importo=='':
#            importo='0'
#        self.spese_importo=Decimal(importo)
#    
#    def set_iva_spese(self,iva):
#        self.iva_spese=iva
#        self.spese_fk_iva=iva.codice
#    
#    def set_intestatario(self,value):
#        self.intestatario=value
#        self.fk_intestatario=value.ID
#    
#    def set_listino(self,listino):
#        if isinstance(listino,basestring):
#            self.codice_listino=listino
#        else:
#            self.codice_listino=listino.codice
#    
#    def calcola_totali(self):
#        tot_imp=0
#        tot_iva=0
#        for riga in self.dettaglio:
#            tot_imp+=riga.get_totale()
#            tot_iva+=riga.get_iva_riga()
#        self.totale_imponibile=tot_imp+self.spese_importo
#        iva_spese=util.round(self.spese_importo/100*self.get_iva_spese())
#        self.totale_iva=tot_iva+iva_spese
#    
#    def save_riga(self,*args,**kwargs):
#        self.dettaglio.save_riga(*args,**kwargs)    
             

#===============================================================================
# Ordine
#===============================================================================
class Ordine(DocumentoBase):
    NUOVO=0
    DA_CONFERMARE=1
    CONFERMATO=2
    PARZ_CONCLUSO=3
    CONCLUSO=4
    ANNULLATO=5
    
    def __init__(self):
        self.ID=None
        self.data=None
        self.data_chiusura=None
        self.stato=None
        self.fk_stato=Ordine.NUOVO
        self.intestatario=None
        self.totale=Decimal('0.00')
        self.totale_imponibile=Decimal('0.00')
        self.totale_iva=Decimal('0.00')
        self.spese_descr=''
        self.spese_iva_perc=Decimal('20.00')
        self.spese_fk_iva=''
        self.spese_importo=Decimal('0.00')
        self.concluso=False
        self.documento=None
        self.dettaglio=[]
        
    def get_rif_documento(self):
        if self.documento is None:
            return ''
        numero=self.documento.numero or self.documento.ID
        return '{0} numero {1} del {2}'.format(self.documento.tipo_documento.descrizione_breve,
                                               numero,
                                               self.documento.get_format_data())

    def get_data_chiusura(self):
        return self.data_chiusura

    def get_stato(self):
        if self.stato is None:
            return ''
        return self.stato.descrizione
    
    def is_concluso(self):
        return self.concluso

    def set_concluso(self):
        self.fk_stato=self.CONCLUSO
        self.concluso=True
    
    def is_editable(self):
        return not self.stato==Ordine.CONCLUSO and \
               not self.stato==Ordine.ANNULLATO

    def set_data_chiusura(self, value):
        self.data_chiusura = value

    def set_stato(self, value):
        '''Il parametro value e' di tipo TipoStatoOrdine.'''
        self.stato = value
        self.fk_stato=value.ID

    def set_dettaglio(self, value):
        assert isinstance(value,Dettaglio),"Ordine: Tipo dettaglio non valido."
        self.dettaglio = value

    def del_dettaglio(self):
        del self.dettaglio

 
#===============================================================================
# OrdineCliente
#===============================================================================
class OrdineCliente(Ordine):
    
    @staticmethod
    def get_new_dettaglio():
        return DettaglioOrdineCliente()
    
    def __init__(self):
        Ordine.__init__(self)
        self.cliente=None
        self.rif_documento=None
    
    def get_cliente(self):
        '''Restituisce il cliente come oggetto.'''
        return self.intestatario
    
    def get_dettaglio(self):
        return (self.dettaglio or DettaglioOrdineCliente())
    
    def set_cliente(self,value):
        '''Setta l'intestatario dell'ordine. value è un oggetto Cliente.'''
        self.intestatario=value
        self.fk_cliente=value.ID

 
#===============================================================================
# OrdineFornitore
#===============================================================================
class OrdineFornitore(Ordine):
    
    @staticmethod
    def get_new_dettaglio():
        return DettaglioOrdineFornitore()
    
    def __init__(self):
        Ordine.__init__(self)
        self.rif_fattura=""        
        self.data_fattura=None
    
    def get_dettaglio(self):
        return (self.dettaglio or DettaglioOrdineFornitore())

    def get_fornitore(self):
        '''Restituisce il fornitore come oggetto.'''
        return self.intestatario

    def get_rif_fattura(self):
        if self.rif_fattura is None:
            return ''
        return self.rif_fattura

    def get_data_fattura(self):
        return self.data_fattura

    def set_rif_fattura(self, value):
        self.rif_fattura = value

    def set_data_fattura(self, value):
        self.data_fattura = value

    def del_fornitore(self):
        del self.intestatario
    
    def set_fornitore(self,value):
        '''Setta l'intestatario dell'ordine. value è un oggetto Fornitore.'''
        self.intestatario=value
        self.fk_fornitore=value.ID


##===============================================================================
## Riga
##===============================================================================
#class Riga(object):
#    def __init__(self):
#        self.numero=None
#        self.prodotto=None
#        self.prezzo=Decimal(0)
#        self.quantita=0
#        self.iva_riga=Decimal(0)
#        self.iva_obj=None
#        self.codice_iva=u''
#        #self.perc_iva=Decimal(0)
#        self.prezzo_fornitore=Decimal(0)
#        self.sconti=u''
#    
##    riga.numero=self._next_num()
##        riga.prodotto=prodotto
##        riga.prezzo=prezzo
##        riga.quantita=quantita
##        riga.iva=iva_riga
##        riga.perc_iva=iva.aliquota
##        riga.codice_iva=iva.codice
#    
#    def set(self,**kw):
#        self.set_numero(kw['numero'])
#        self.set_prodotto(kw['prodotto'])
#        self.set_prezzo(kw['prezzo'])
#        self.set_quantita(kw['quantita'])
#        self.set_iva(kw['iva'])
#        self.set_sconti(kw.pop('sconti',''))
#        
#    def get_numero(self):
#        return str(self.numero)
#
#    def get_prodotto(self):
#        return self.prodotto
#
#    def get_quantita(self):
#        return self.quantita
#    
#    def get_iva_riga(self):
#        if self.iva_obj is not None:
#            self._aggiorna_iva_riga()
#        return self.iva_riga
#    
#    def get_iva_riga_fmt(self):
#        return util.euro(self.get_iva_riga())
#    
#    def get_codice_iva(self):
#        return self.codice_iva
#    
#    def get_prezzo(self):
#        return self.prezzo
#    
#    def get_prezzo_fmt(self):
#        return util.euro(self.get_prezzo())
#    
#    def get_totale(self):
#        '''Totale senza iva.'''
#        return util.round(self.prezzo*self.quantita)
#    
#    def get_totale_fmt(self):
#        return util.euro(self.get_totale())
#    
#    def get_iva_perc(self):
#        if self.iva_obj is None:
#            return Decimal('0.00')
#        return self.iva_obj.aliquota
#    
#    def get_sconti(self):
#        if self.sconti is None:
#            self.sconti=''
#        return self.sconti
#    
#    def set_sconti(self,value):
#        self.sconti=value
#        #self._calcola_sconto()
#
#    def set_numero(self, value):
#        self.numero = int(value)
#
#    def set_prodotto(self, value):
#        assert isinstance(value,Prodotto),"Riga: Tipo prodotto non valido."
#        self.prodotto = value
#
#    def set_quantita(self, value):
#        self.quantita = int(value)
#    
#    def set_iva(self,value):
#        self.codice_iva=value.codice
#        self.iva_obj=value
#        self._aggiorna_iva_riga()
#    
#    def set_iva_riga(self,value):
#        self.iva_riga=Decimal(value)
#    
#    def set_codice_iva(self,codice):
#        self.codice_iva=codice
#    
##    def set_perc_iva(self,perc_iva):
##        self.perc_iva=Decimal(perc_iva)
#    
#    def set_prezzo(self,value):
#        self.prezzo=Decimal(value)
#
#    def del_prodotto(self):
#        del self.prodotto
#    
#    def da_movimentare(self):
#        return not self.prodotto.is_servizio()
#    
#    def _aggiorna_iva_riga(self):
#        iva_perc=self.get_iva_perc()
#        self.iva_riga=util.round((self.prezzo*iva_perc/100)*self.quantita)


#===============================================================================
# RigaOrdineFornitore
#===============================================================================
class RigaOrdineFornitore(Riga):
    def __init__(self):
        super(RigaOrdineFornitore,self).__init__()


#===============================================================================
# RigaOrdineCliente
#===============================================================================
class RigaOrdineCliente(Riga):
    def __init__(self):
        super(RigaOrdineCliente,self).__init__()
        

##===============================================================================
## RigaDocumento
##===============================================================================
#class RigaDocumento(Riga):
#    def __init__(self):
#        super(RigaDocumento,self).__init__()
        

#===============================================================================
# RigaVenditaBanco
#===============================================================================
class RigaVenditaBanco(Riga):
    def __init__(self):
        super(RigaVenditaBanco,self).__init__()
        self.movimentata=False
    
    #def da_movimentare(self):
        #return not self.movimentata and super(RigaVenditaBanco,self).da_movimentare()
    
    def set_movimentata(self):
        self.movimentata=True
        

##===============================================================================
## Dettaglio
##===============================================================================
#class Dettaglio(list):
#    def __init__(self):
#        super(Dettaglio,self).__init__()
#        self.cont=0
#    
#    def _get_nuova_riga(self):
#        '''OVERRIDE IN SUBCLASS!'''
#        raise
#                     
#    def _next_num(self):
#        if len(self)==0:
#            self.cont=0
#        return self.cont+1
#    
#    def append(self,riga):        
#        if riga.numero>self.cont:
#            self.cont=riga.numero
#        super(Dettaglio,self).append(riga)
#    
#    def save_riga(self,**kwargs):
#        '''Aggiunge o aggiorna una riga documento.'''
#        numero=kwargs.pop('numero','')
#        prodotto=kwargs['prodotto']
#        prezzo=Decimal(kwargs['prezzo'])
#        quantita=int(kwargs['quantita'])
#        iva=kwargs['iva']
#        sconti=kwargs.pop('sconti','')           
#        
#        riga=self.find_riga(numero)
#        if riga is None:
#            riga=self._get_nuova_riga()
#            riga.numero=self._next_num()
#            self.append(riga)##TODO: controllare se funziona!
#        riga.set(numero=riga.numero,
#                 prodotto=prodotto,
#                 prezzo=prezzo,
#                 quantita=quantita,
#                 iva=iva,
#                 sconti=sconti)
#        #riga.perc_iva=iva.aliquota
#        #riga.codice_iva=iva.codice
#        
#    def add_riga_(self,*args,**kwargs):
#        '''Aggiunge una nuova riga documento. A differenza di save_riga, che accetta l'iva come oggetto,
#        prende i parametri iva_riga e codice_iva.Adatto se si conosce gia' l'importo iva della riga.'''
#        prodotto=kwargs['prodotto']
#        prezzo=Decimal(kwargs['prezzo'])
#        quantita=int(kwargs['quantita'])
#        iva_riga=kwargs['iva_riga']
#        codice_iva=kwargs['codice_iva']
#        sconti=kwargs.pop('sconti','')                
#    
#        riga=self._get_nuova_riga()
#        riga.set_numero(self._next_num())
#        riga.set_prodotto(prodotto)
#        riga.set_prezzo(prezzo)
#        riga.set_quantita(quantita)
#        riga.set_iva_riga(iva_riga)
#        riga.set_codice_iva(codice_iva)
#        riga.set_sconti(sconti)
#        #riga.perc_iva=iva.aliquota
#        #riga.codice_iva=iva.codice
#        self.append(riga)
#    
#    def _update_riga_(self,*args,**kwargs):
#        '''Aggiorna una riga esistente con i nuovi valori.'''
#        numero=int(kwargs['numero'])
#        prodotto=kwargs['prodotto']
#        prezzo=Decimal(kwargs['prezzo'])
#        quantita=int(kwargs['quantita'])
#        iva=kwargs['iva']
#        sconti=kwargs.pop('sconti','')
#        
#        #iva_riga=util.round((prezzo*iva.aliquota/100)*quantita)        
#    
#        riga=self.find_riga(numero)
#        if riga is None:
#            raise Exception('Riga {0} non trovata: nessuna riga da aggiornare.'.format(numero))
#            return False
#        riga.set(numero=riga.numero,prodotto=prodotto,
#                 prezzo=prezzo,
#                 quantita=quantita,
#                 iva=iva,
#                 sconti=sconti)
#        #riga.perc_iva=iva.aliquota
#        #riga.codice_iva=iva.codice
#        return True
#            
##    def add_riga(self,*args,**kwargs):
##        '''DEPRECATO Aggiunge una nuova riga documento.'''
##        print 'Metodo deprecato: Dettaglio.add_riga(...)'
##        prodotto=kwargs['prodotto']
##        prezzo=Decimal(kwargs['prezzo'])
##        quantita=int(kwargs['quantita'])
##        perc_iva=Decimal(kwargs['perc_iva'])
##        
##        iva=util.round((prezzo*perc_iva/100)*quantita)                
##    
##        riga=self._get_nuova_riga()
##        riga.numero=self._next_num()
##        riga.prodotto=prodotto
##        riga.prezzo=prezzo
##        riga.quantita=quantita
##        riga.iva=iva
##        riga.perc_iva=perc_iva
##        self.append(riga)
##    
##    def update_riga(self,*args,**kwargs):
##        '''Aggiorna una riga esistente con i nuovi valori.'''
##        numero=int(kwargs['numero'])
##        prodotto=kwargs['prodotto']
##        prezzo=Decimal(kwargs['prezzo'])
##        quantita=int(kwargs['quantita'])
##        perc_iva=Decimal(kwargs['perc_iva'])
##        
##        iva=util.round((prezzo*perc_iva/100)*quantita)        
##    
##        riga=self.find_riga(numero)
##        if riga is None:
##            raise Exception('Riga {0} non trovata: nessuna riga da aggiornare.'.format(numero))
##            return False
##        riga.prodotto=prodotto
##        riga.prezzo=prezzo
##        riga.quantita=quantita
##        riga.iva=iva
##        riga.perc_iva=perc_iva
##        return True
#    
#    def find_riga(self,numero):
#        if numero=='':
#            return None
#        numero=int(numero)
#        for item in self:
#            if item.numero==numero:
#                return item
#        return None
  
    
#===============================================================================
# DettaglioOrdineCliente
#===============================================================================
class DettaglioOrdineCliente(Dettaglio):
    def __init__(self):
        super(DettaglioOrdineCliente,self).__init__()
        
    def _get_nuova_riga(self):
        return RigaOrdineCliente()


#===============================================================================
# DettaglioOrdine
#===============================================================================
class DettaglioOrdineFornitore(Dettaglio):
    def __init__(self):
        super(DettaglioOrdineFornitore,self).__init__()
    
    def _get_nuova_riga(self):
        return RigaOrdineFornitore()


#===============================================================================
# DettaglioDocumento
#===============================================================================
#class DettaglioDocumento(Dettaglio):
#    def __init__(self):
#        super(DettaglioDocumento,self).__init__()
#                     
#    def _get_nuova_riga(self):
#        return RigaDocumento()


#===============================================================================
# DettaglioVenditaBanco
#===============================================================================
class DettaglioVenditaBanco(Dettaglio):
    def __init__(self):
        super(DettaglioVenditaBanco,self).__init__()
    
    def _get_nuova_riga(self):
        return RigaVenditaBanco()


#===============================================================================
# DettaglioRegistrazione
#===============================================================================
class DettaglioRegistrazione(Dettaglio):
    def __init__(self):
        super(DettaglioRegistrazione,self).__init__()
    
    def _get_nuova_riga(self):
        return RigaRegistrazione()

    def save_riga(self,**kwargs):
        '''Aggiunge o aggiorna una riga alla registrazione.'''
        numero=kwargs.pop('numero','')
        imponibile=kwargs['imponibile']
        descrizione=kwargs['descrizione']
        iva=kwargs['iva']
        sconti=kwargs.pop('sconti','')           
        
        riga=self.find_riga(numero)
        if riga is None:
            riga=self._get_nuova_riga()
            riga.numero=self._next_num()
            self.append(riga)##TODO: controllare se funziona!
        riga.set(numero=riga.numero,
                 imponibile=imponibile,
                 iva=iva,
                 descrizione=descrizione,
                 sconti=sconti)
        
    def add_riga_(self,*args,**kwargs):
        '''Aggiunge una nuova riga alla registrazione. A differenza di save_riga, che accetta l'iva come oggetto,
        prende i parametri iva_riga e codice_iva.Adatto se si conosce gia' l'importo iva della riga.'''
        descrizione=kwargs['descrizione']
        imponibile=Decimal(kwargs['imponibile'])
        iva_riga=kwargs['iva_riga']
        codice_iva=kwargs['codice_iva']
        sconti=kwargs.pop('sconti','')                
    
        riga=self._get_nuova_riga()
        riga.set_numero(self._next_num())
        riga.set_descrizione(descrizione)
        riga.set_imponibile(imponibile)
        riga.set_iva_riga(iva_riga)
        riga.set_codice_iva(codice_iva)
        riga.set_sconti(sconti)
        self.append(riga)
    

##===============================================================================
## TipoDocumento
##===============================================================================
#class TipoDocumento(object):
#    def __init__(self):
#        self.ID=None
#        self.descrizione=''
#    
#    def get_ID(self):
#        return self.ID
#    
#    def set_ID(self,value):
#        self.ID=util.none_if_not(value)
    

#===============================================================================
# Contatore
#===============================================================================
#class Contatore(object):
#    def __init__(self):
#        self.contatore=0

#===============================================================================
# Documento
#===============================================================================
#class Documento(DocumentoBase):
#    FATTURA=1
#    FATTURA_ACC=2
#    DDT=3
#    ARRIVO_MERCE=10
#    
#    @staticmethod
#    def get_new_dettaglio():
#        return DettaglioDocumento()
#            
#    def __init__(self):
#        self.ID=None
#        self.numero=None
#        self.data=None
#        self.tipo_documento=None
#        self.fk_tipo_documento=None
#        self.intestatario=None
#        self.destinazione=None
#        self.dettaglio=[]
#        #fattura
#        self.ordine=None
#        #ddt
#        self.causale=None
#        self.data_traporto=None
#        self.porto=None
#        self._incaricato_trasporto=None
#        self.numero_colli=None
#        self.peso=None
#        self.aspetto_beni=None
#        #arrivo merce
#        self.registrazione=None
#        #spese e totali
#        self.totale=Decimal('0.00')
#        self.totale_imponibile=Decimal('0.00')
#        self.totale_iva=Decimal('0.00')
#        self.spese_descr=''
#        self.spese_iva_perc=Decimal('20.00')
#        self.spese_fk_iva=''
#        self.spese_importo=Decimal('0.00')
#    
#    def is_fattura(self):
#        return self.fk_tipo_documento==Documento.FATTURA
#    
#    def is_ddt(self):
#        return self.fk_tipo_documento==Documento.DDT
#    
#    def is_fattura_acc(self):
#        return self.fk_tipo_documento==Documento.FATTURA_ACC
#    
#    def is_arrivo(self):
#        return self.fk_tipo_documento==Documento.ARRIVO_MERCE
#
#    def get_registrazione(self):
#        if not hasattr(self,'registrazione') or self.registrazione is None:
#            return u''
#        return '{0} numero {1} del {2}'.format(self.registrazione.tipo_documento.descrizione_breve,
#                                               self.registrazione.ID,
#                                               self.registrazione.get_format_data())
#        
#   
#    def get_numero(self):
#        return self.numero
#
#    def get_tipo_documento(self):
#        return self.tipo_documento.descrizione
#    
#    def get_ordine(self):
#        return self.ordine
#
#    def set_ordine(self, value):
#        self.ordine = value
#
#    def del_ordine(self):
#        del self.ordine
#
#    def set_numero(self, value):
#        self.numero = value
#
#    def set_tipo_documento(self,value):
#        self.tipo=value
#        self.fk_tipo_documento=value.ID
#    
#    def is_editable(self):
#        return self.ID is None
#        #return True


#===============================================================================
# VenditaBanco
#===============================================================================
class VenditaBanco(DocumentoBase):
    
    @staticmethod
    def get_new_dettaglio():
        return DettaglioVenditaBanco()
    
    def __init__(self):
        self.totale=Decimal('0.00')
        self.totale_imponibile=Decimal('0.00')
        self.totale_iva=Decimal('0.00')
        self.spese_descr=''
        self.spese_fk_iva=''
        self.spese_importo=Decimal('0.00')
        self.fatturato=False
        self.dettaglio=[]
    
    def is_editable(self):
        return not self.is_fatturato()
    
#    def set_ID(self, value):
#        self.ID = util.none_if_not(value)
    
#    def get_ID(self):
#        return self.ID
    
    def get_rif_documento(self):
        if self.documento is None:
            return ''
        return '{0} numero {1} del {2}'.format(self.documento.tipo_documento.descrizione_breve,
                                               self.documento.numero,
                                               self.documento.get_format_data())
    
#    def get_format_data(self):
#        if isinstance(self.data,date):
#            return self.data.strftime('%d/%m/%Y')
#        return self.data
    
    def get_cliente(self):
        return self.get_intestatario()
    
    def is_fatturato(self):
        if self.fatturato is None:
            self.fatturato=False
        return self.fatturato
    
    def set_fatturato(self):
        self.fatturato=True
    
#    def calcola_totali(self):
#        tot_imp=0
#        tot_iva=0
#        for riga in self.dettaglio:
#            tot_imp+=riga.get_totale()
#            tot_iva+=riga.get_iva()
#        self.totale_imponibile=tot_imp
#        self.totale_iva=tot_iva
#    
#    def get_totale(self):
#        return self.totale_imponibile+self.totale_iva
                
##===============================================================================
## Fattura
##===============================================================================
#class Fattura(Documento):
#    def __init__(self):
#        Documento.__init__(self)
#        self.fk_tipo_documento=Documento.FATTURA   
#
#
##===============================================================================
## DDT
##===============================================================================
#class DDT(Documento):
#    def __init__(self):
#        Documento.__init__(self)
#        self.fk_tipo_documento=Documento.DDT
#        
#
##===============================================================================
## FatturaAccompagnatoria
##===============================================================================
#class FatturaAccompagnatoria(Documento):
#    def __init__(self):
#        Documento.__init__(self)
#        self.fk_tipo_documento=Documento.FATTURA_ACC
                

##===============================================================================
## MovimentoMagazzino
##===============================================================================
#class MovimentoMagazzino(object):
#    CARICO=1
#    SCARICO=2
#    ESISTENTE=3
#    CARICO_MANUALE=4
#    SCARICO_MANUALE=5
#    SCARICO_BANCO=6
#    def __init__(self):
#        self.ID=None
#        self.data=date.today()
#        self.causale=None
#        self.prodotto=None
#        self.quantita=0
#        self.note=None
#        self.rif_fattura=None
#    
#    def get_data_fmt(self):
#        return util.format_date(self.data)
#    
#    def set_ID(self,value):
#        self.ID=util.none_if_not(value)
#    
#    def set_causale(self,causale):
#        self.causale=causale
#        self.fk_causale=causale.ID
#    
#    def set_prodotto(self,prodotto):
#        self.prodotto=prodotto
#        self.fk_prodotto=prodotto.ID
#    
#    def set_quantita(self,qta):
#        if qta=='':
#            qta=0
#        self.quantita=int(qta)
#
#    
##===============================================================================
## CausaleMovimento
##===============================================================================
#class CausaleMovimento(object):
#    def __init__(self):
#        self.ID=None
#        self.descrizione=''
#        self.segno=1
#    
#    def set_ID(self,value):
#        self.ID=util.none_if_not(value)
#        
#
##===============================================================================
## Spese
##===============================================================================
#class Spese(object):
#    def __init__(self):
#        self.ID=None
#        self.iva=None
#        self.descizione=''
#        self.importo=Decimal(0)
#    
#    def set_ID(self,value):
#        self.ID=util.none_if_not(value)


##===============================================================================
## Lavagna
##===============================================================================
#class Lavagna(object):
#    def __init__(self):
#        self.ID=0
#        self.contenuto=''
#    
#    def set_contenuto(self,value):
#        self.ID=0
#        self.contenuto=value





#===============================================================================
# Opzione
#===============================================================================
#class Opzione(object):
#    def __init__(self):
#        self.chiave=''
#        self.valore=''
#    
#
##==============================================================================
## Opzioni
##==============================================================================
#class Opzioni(list):
#    '''Mantiene una lista di oggetti Opzione. '''
#    
#    dirty=False
#    
#    @staticmethod
#    def is_dirty():
#        return Opzioni.dirty
#    @staticmethod
#    def set_dirty(dirty=True):
#        Opzioni.dirty=dirty
#    
#    def __init__(self):
#        super(Opzioni,self).__init__()
#    
#    def __getattribute__(self,name):
#        for opt in self:
#            if opt.chiave==name:
#                return opt.valore
#        try:
#            attr=super(Opzioni,self).__getattribute__(name)
#        except AttributeError:
#            o=Opzione()
#            o.chiave=name
#            self.append(o)
#            attr=o.valore
#        return attr
#    
#    def __setattr__(self,name,value):
#        for opt in self:
#            if opt.chiave==name:
#                opt.valore=str(value)
#        return super(Opzioni,self).__setattr__(name,value)


#===============================================================================
# OpzioniDb
#===============================================================================
#class InfoConnessione(dict):
#    def __init__(self):
#        dict.__init__(self)
#        self['backend']='mysql'
#        self['dbname']='koro'
#        self['user']='root'
#        self['passwd']='or8pale12'
#        self['port']='3306'
#        self['host']='localhost'
#        
#    def __getattribute__(self,name):
#        if name in self:
#            return self[name]
#        return super(InfoConnessione,self).__getattribute__(name)
#    
#    def __setattr__(self,name,value):
#        if name in self:
#            self[name]=value
#            return
#        super(InfoConnessione,self).__setattr__(name,value)


#===============================================================================
# Azienda
#===============================================================================
#class Azienda(Anagrafica):
#    def __init__(self):
#        super(Azienda,self).__init__()    


#===============================================================================
# RegFatturaFornitore
#===============================================================================
class Registrazione(object):
    def __init__(self):
        super(Registrazione,self).__init__()
        self.ID=None
        self.data=None,
        self.fk_tipo_documento=None  
        self.fk_fornitore=None
        self.num_fatt_forn=u''
        self.data_fatt_forn=None
        self.totale_imponibile=Decimal('0.00')
        self.totale_iva=Decimal('0.00')
        self.codice_listino=u''
        self.note=u''
        self.rif_documento=None
    
    def set_ID(self,value):
        self.ID=util.none_if_not(value)
        

#===============================================================================
# RigheRegFatturaFornitore
#===============================================================================
class RigaRegistrazione(object):
    def __init__(self):
        super(RigaRegistrazione,self).__init__()
        self.fk_registrazione=None,
        self.numero=0
        self.imponibile_riga=Decimal('0.00')
        self.iva_riga=Decimal('0.00')
        self.codice_iva=u''
        self.sconti=u''
        self.descrizione=u''
    
    def set(self,**kw):
        self.set_numero(kw['numero'])
        self.set_descrizione(kw['descrizione'])
        self.set_imponibile(kw['imponibile'])
        self.set_iva(kw['iva'])
        self.set_sconti(kw.pop('sconti',''))
        
    def get_numero(self):
        return str(self.numero)
    
    def get_descrizione(self):
        return self.descrizione
    
    def get_iva_riga(self):
        if self.iva_obj is not None:
            self._aggiorna_iva_riga()
        return self.iva_riga
    
    def get_iva_riga_fmt(self):
        return util.euro(self.get_iva_riga())
    
    def get_codice_iva(self):
        return self.codice_iva
    
    def get_imponibile(self):
        return self.imponibile_riga
    
    def get_prezzo_fmt(self):
        return util.euro(self.get_imponibile())
    
    def get_totale(self):
        '''Totale senza iva.'''
        return util.round(self.imponibile_riga)
    
    def get_totale_fmt(self):
        return util.euro(self.get_totale())
    
    def get_iva_perc(self):
        if self.iva_obj is None:
            return Decimal('0.00')
        return self.iva_obj.aliquota
    
    def get_sconti(self):
        if self.sconti is None:
            self.sconti=''
        return self.sconti
    
    def set_sconti(self,value):
        self.sconti=value
        #self._calcola_sconto()

    def set_numero(self, value):
        self.numero = int(value)

    def set_descrizione(self, value):
        self.descrizione = value
    
    def set_iva(self,value):
        self.codice_iva=value.codice
        self.iva_obj=value
        self._aggiorna_iva_riga()
    
    def set_iva_riga(self,value):
        self.iva_riga=Decimal(value)
    
    def set_codice_iva(self,codice):
        self.codice_iva=codice
    
    def set_imponibile(self,value):
        self.imponibile_riga=Decimal(value)
    
    def _aggiorna_iva_riga(self):
        iva_perc=self.get_iva_perc()
        self.iva_riga=util.round((self.imponibile_riga*iva_perc/100))